--[[
-- @Author:	grayson
-- @DateTime: 2020-10-30 23:05:48
-- @Description: 作为客户端连接go的服务端使用

local function test3()
	local go_net = new("go_net")
	local ip = "127.0.0.1"
	local port = 5051
	go_net:connect(ip, port)
	local data = {
		527, 1990, "SSD", 1119,
		level = 20,
		name = "lakefu",
		attrs = {
			[100] = "hp",
			mp = 80.75
		}
	}
	go_net:send("test", data)

	g.register("test", function(msg)
		g.log:warn("res:", msg)
	end)
end

--]]

local skynet = require("skynet")
local socket = require("skynet.socket")


local HEAD_LEN = 4
local PACK_FMT  = string.format(">I%d",HEAD_LEN)
--消息打包类
local M = class("M")


function M:ctor()
    self.fd = nil
    self.ip = nil
    self.port = nil
    self.last_package = ""
    self.msg_callbacks = {} --消息回调列表
    self.session = math.random(1,100000)

    --接收消息
    g.fork(function()
        while true do
            -- print(">>>M:recv_loop>>>")
            if self.fd then
                local ok, str, close_reason = pcall(socket.read, self.fd)
                if ok and str then
                    self:receive(str)
                else
                    g.log:error("接收数据错误,关闭fd:", self.fd, str, close_reason)
                    self:close(self.fd, close_reason)
                end
                g.sleep(100)
            else
                g.sleep(100)
            end
        end
    end)
end

--取大端2个字节
function M:readShortBig( text ) --big endian
    return text:byte(1)*256 + text:byte(2)
end

--包长度2字节（skynet 规定头2个字节为包长度
function M:unpackPackage(text)
    local size = #text
    if size < 2 then
        return nil, text
    end
    local pack_size = self:readShortBig(text)
    if size < pack_size + 2 then
        return nil, text
    end
    local offset = 2
    local msg = text:sub(offset + 1, offset + pack_size)
    local last = text:sub(offset + 1 + pack_size)
    return msg, last
end

--连接socket
function M:connect(ip, port)
    local protocol = "ws"
    local url = string.format("%s://%s:%s/test_websocket", protocol, ip , port)
    if not ip or not port then
        print("M:connect ip port is nill___")
        return false
    end
    self.ip = ip
    self.port = port
    self.fd =  socket.open(self.ip, self.port)
    if not self.fd then
        print("连接 "..ip..":"..port.."失败")
        return false
    end
    print("########连接"..ip..":"..port.."成功#########")
    return true
end

function M:receive(str)
    print("收到数据"..#str)
    self.last_package = self.last_package .. str
    local recv_buffer = self.last_package

    local body_len, next_pos = string.unpack(PACK_FMT, recv_buffer)
    if #recv_buffer < body_len + HEAD_LEN then
        return
    end
    assert(#recv_buffer == body_len + HEAD_LEN, "reply stream overflow")
    local stream = recv_buffer:sub(next_pos)
    local cmd, msg =  skynet.unpack(stream)
    
    local ok , result = xpcall(g.dispatch.dispatchMessage, g.handle_err, g.dispatch, nil, nil, cmd, msg)
    if ok then
        if result then
            return
        end
    else
        g.log:error(result)
        return
    end
    --g.log:info("msg receive no dispatch", tostring(u_msg))
end

function M:close(fd, close_reason)
    print("M:close fd:",self.fd)
    if self.fd then
        socket.close(self.fd, close_reason)
    end
    self.fd = nil
end

function M:send(msg_name, msg_body)
    if not self.fd then
        local conn = self:connect(self.ip, self.port)
        if not conn then
            --连接失败            
            return
        end
    end
    --self.client_pack:clientSend(self.fd, msg_name, msg_body, conn_type)
    local body = skynet.packstring(msg_name, msg_body)
    local head = string.pack(PACK_FMT,#body)
    local pkg = head .. body
    local ok, err = xpcall(socket.write, debug.traceback, self.fd, pkg)
    if not ok then
        g.log:error('go_net:send faild:', err)
        return false
    end
end


return M